package message

import (
	"bytes"
	"errors"
	"fmt"

	"github.com/ethereum/go-ethereum/rlp"
	commtypes "hundsun.com/hsl/hschain/common/types"
	"hundsun.com/hsl/hschain/consensus/types"
	"hundsun.com/hsl/hschain/protos/p2p"
)

// EncodeMessage 消息编码成P2PMsg，后续发送到p2p进行转发
func EncodeMessage(peerID string, msg *types.ConsensRelayMsg) (*p2p.P2PMsg, error) {
	var p2pMsg = &p2p.P2PMsg{}
	var buf bytes.Buffer
	switch msg.MsgType {
	case types.ConsensusVoteMsg, types.ConsensusCommitMsg, types.ConsensusEndorserMsg:
		p2pMsg.MsgType = commtypes.EventConsensusRequestMsg
		p2pMsg.TargetMod = commtypes.ConsensusModule
	case types.BlockSequenceAddBlockMsg, types.BlockSequenceRequestMsg:
		p2pMsg.MsgType = commtypes.EventConsensusRequestMsg
		p2pMsg.TargetMod = commtypes.SequenceCenterModule
	case types.ConsensusVoteRespMsg, types.ConsensusCommitRespMsg, types.ConsensusEndorserRespMsg, types.BlockSequenceAddBlockRespMsg, types.BlockSequenceResponseMsg:
		p2pMsg.MsgType = commtypes.EventConsensusResponseMsg
		p2pMsg.TargetMod = commtypes.ConsensusModule
	case types.UnknownRelayMsg:
	default:
		return nil, errors.New("Unsupported message type")
	}

	err := rlp.Encode(&buf, msg.MsgType)
	if err != nil {
		return nil, err
	}
	err = rlp.Encode(&buf, msg)
	if err != nil {
		return nil, err
	}

	p2pMsg.TargetPeerId = peerID
	p2pMsg.Payload = buf.Bytes()

	return p2pMsg, nil
}

// DecodeMessage p2p收到的其他共识节点的消息，共识模块解码后进行内部处理
func DecodeMessage(msg *p2p.P2PMsg) (*types.ConsensRelayMsg, error) {
	payload := msg.GetPayload()
	if len(payload) <= 1 {
		return nil, fmt.Errorf("Invalid message size")
	}
	var msgType types.RelayMsgType
	err := rlp.DecodeBytes(payload[:1], &msgType)
	if err != nil {
		return nil, err
	}

	var resp = &types.ConsensRelayMsg{}
	resp.MsgType = msgType
	err = rlp.DecodeBytes(payload[1:], resp)
	return resp, err
}
